/**
* @File:file.c
* @Version:V1.0
* @Author:tokamak
* @Brief:
* @Logs:
* 	Date		Author		Notes
* 	2025-06-12	tokamak		first version
* @Note:The MFRC522 can generate an interrupt signal when:
*• ComIEnReg register’s LoAlertIEn bit is set to logic 1. It activates pin IRQ when
*	Status1Reg register’s LoAlert bit changes to logic 1.
*• ComIEnReg register’s HiAlertIEn bit is set to logic 1. It activates pin IRQ when
*	Status1Reg register’s HiAlert bit changes to logic 1.
*/

// <<< Use Configuration Wizard in Context Menu >>>

/* Private includes --------------------------------------------------------- */
#include "mfrc522.h"
#include "board.h"
#ifdef __cplusplus
extern
{
#endif

	/* Private config ----------------------------------------------------------- */
	/* Private defines ---------------------------------------------------------- */
	/* Private typedef ---------------------------------------------------------- */
	/* Private variables -------------------------------------------------------- */
	/* Private function prototypes ---------------------------------------------- */

	/*----------------------------------------------------------------------------*/
	/* Private functions -------------------------------------------------------- */

	/* Public functions --------------------------------------------------------- */
#include "mfrc522.h"
#include <rtthread.h>

// MFRC522设备链表头
	static rt_list_t mfrc522_device_list = RT_LIST_OBJECT_INIT(mfrc522_device_list);

// 复位时间（毫秒）
#define MFRC522_RESET_TIME 1

	rt_err_t mfrc522_init(mfrc522_device * dev, const char* i2c_bus_name,
	                      uint8_t i2c_addr, rt_base_t rst_pin, const char* name)
	{
		RT_ASSERT(dev != RT_NULL);
		RT_ASSERT(i2c_bus_name != RT_NULL);
		RT_ASSERT(name != RT_NULL);

		// 查找I2C总线设备
		dev->i2c_bus = rt_i2c_bus_device_find(i2c_bus_name);
		if(dev->i2c_bus == RT_NULL)
		{
			rt_kprintf("MFRC522: I2C bus '%s' not found!\n", i2c_bus_name);
			return -RT_ERROR;
		}

		// 初始化设备参数
		dev->i2c_addr = i2c_addr;
		dev->rst_pin = rst_pin;
		rt_strncpy(dev->name, name, RT_NAME_MAX);

		// 初始化复位引脚
		if(rst_pin != RT_NULL)
		{
			rt_pin_mode(rst_pin, PIN_MODE_OUTPUT);
			rt_pin_write(rst_pin, PIN_HIGH);
		}

		// 执行硬件复位
		if(rst_pin != RT_NULL)
		{
			rt_pin_write(rst_pin, PIN_LOW);
			rt_thread_mdelay(MFRC522_RESET_TIME);
			rt_pin_write(rst_pin, PIN_HIGH);
			rt_thread_mdelay(MFRC522_RESET_TIME);
		}

		// 执行软复位
		mfrc522_soft_reset(dev);

		// 配置设备
		mfrc522_write_reg(dev, MFRC522_REG_T_MODE, 0x80);     // TAuto=1
		mfrc522_write_reg(dev, MFRC522_REG_T_PRESCALER, 0xA9); // TPreScaler = 169
		mfrc522_write_reg(dev, MFRC522_REG_T_RELOAD_H, 0x03);  // Reload timer high
		mfrc522_write_reg(dev, MFRC522_REG_T_RELOAD_L, 0xE8);  // Reload timer low
		mfrc522_write_reg(dev, MFRC522_REG_TX_CONTROL, 0x03); // Enable TX1 and TX2
		mfrc522_write_reg(dev, MFRC522_REG_RF_CFG, 0x70);     // Receiver gain

		// 添加到设备链表
		rt_list_init(&dev->list);
		rt_list_insert_after(&mfrc522_device_list, &dev->list);

		rt_kprintf("MFRC522 device '%s' initialized on I2C bus '%s'\n", name, i2c_bus_name);
		return RT_EOK;
	}

	mfrc522_device * mfrc522_find(const char* name)
	{
		rt_list_t* node;
		mfrc522_device* dev;

		rt_list_for_each(node, &mfrc522_device_list)
		{
			dev = rt_list_entry(node, mfrc522_device, list);
			if(rt_strcmp(dev->name, name) == 0)
			{
				return dev;
			}
		}

		return RT_NULL;
	}

	void mfrc522_write_reg(mfrc522_device * dev, MFRC522_Register reg, uint8_t data)
	{
		RT_ASSERT(dev != RT_NULL);

		struct rt_i2c_msg msg[2];
		uint8_t buf[2];

		// 准备数据
		buf[0] = reg;
		buf[1] = data;

		// 准备I2C消息
		msg[0].addr = dev->i2c_addr;
		msg[0].flags = RT_I2C_WR;
		msg[0].buf = buf;
		msg[0].len = 2;

		// 发送数据
		if(rt_i2c_transfer(dev->i2c_bus, msg, 1) != 1)
		{
			rt_kprintf("MFRC522 write reg 0x%02X failed!\n", reg);
		}
	}

	uint8_t mfrc522_read_reg(mfrc522_device * dev, MFRC522_Register reg)
	{
		RT_ASSERT(dev != RT_NULL);

		struct rt_i2c_msg msg[2];
		uint8_t reg_addr = reg;
		uint8_t data = 0;

		// 写寄存器地址
		msg[0].addr = dev->i2c_addr;
		msg[0].flags = RT_I2C_WR;
		msg[0].buf = &reg_addr;
		msg[0].len = 1;

		// 读数据
		msg[1].addr = dev->i2c_addr;
		msg[1].flags = RT_I2C_RD;
		msg[1].buf = &data;
		msg[1].len = 1;

		// 执行传输
		if(rt_i2c_transfer(dev->i2c_bus, msg, 2) != 2)
		{
			rt_kprintf("MFRC522 read reg 0x%02X failed!\n", reg);
			return 0;
		}

		return data;
	}

	rt_bool_t mfrc522_detect_card(mfrc522_device * dev)
	{
		RT_ASSERT(dev != RT_NULL);

		// 清除寄存器
		mfrc522_write_reg(dev, MFRC522_REG_COMMAND, MFRC522_CMD_IDLE);
		mfrc522_write_reg(dev, MFRC522_REG_FIFO_LEVEL, 0x80); // Flush FIFO

		// 发送检测命令
		mfrc522_write_reg(dev, MFRC522_REG_FIFO_DATA, 0x26); // REQA命令
		mfrc522_write_reg(dev, MFRC522_REG_COMMAND, MFRC522_CMD_TRANSCEIVE);
		mfrc522_write_reg(dev, MFRC522_REG_BIT_FRAMING, 0x87); // StartSend=1

		// 等待响应
		rt_uint16_t i;
		for(i = 2000; i > 0; i--)
		{
			uint8_t n = mfrc522_read_reg(dev, MFRC522_REG_COMMAND);
			if(!(n & (1 << 2)))    // IdleIRq bit
			{
				rt_thread_mdelay(1);
			}
			else
			{
				break;
			}
		}

		// 检查是否有响应
		if(i > 0)
		{
			// 使用Status2寄存器替代Error寄存器
			uint8_t status = mfrc522_read_reg(dev, MFRC522_REG_STATUS2);
			if(status & 0x08)    // 检查RxIRq标志（收到数据）
			{
				return RT_TRUE;
			}
		}

		return RT_FALSE;
	}

	MFRC522_Status mfrc522_read_uid(mfrc522_device * dev, MFRC522_Uid * uid)
	{
		RT_ASSERT(dev != RT_NULL);
		RT_ASSERT(uid != RT_NULL);

		// 清除寄存器
		mfrc522_write_reg(dev, MFRC522_REG_COMMAND, MFRC522_CMD_IDLE);
		mfrc522_write_reg(dev, MFRC522_REG_FIFO_LEVEL, 0x80); // Flush FIFO

		// 发送防碰撞命令
		uint8_t cmd[] = {0x93, 0x20}; // ANTICOLL + NVB
		for(int i = 0; i < sizeof(cmd); i++)
		{
			mfrc522_write_reg(dev, MFRC522_REG_FIFO_DATA, cmd[i]);
		}

		// 发送命令
		mfrc522_write_reg(dev, MFRC522_REG_COMMAND, MFRC522_CMD_TRANSCEIVE);
		mfrc522_write_reg(dev, MFRC522_REG_BIT_FRAMING, 0x87); // StartSend=1

		// 等待响应
		rt_uint16_t i;
		for(i = 2000; i > 0; i--)
		{
			uint8_t n = mfrc522_read_reg(dev, MFRC522_REG_COMMAND);
			if(!(n & (1 << 2)))    // IdleIRq bit
			{
				rt_thread_mdelay(1);
			}
			else
			{
				break;
			}
		}

		if(i == 0)
		{
			return STATUS_TIMEOUT;
		}

		// 使用Status2寄存器替代Error寄存器
		uint8_t status = mfrc522_read_reg(dev, MFRC522_REG_STATUS2);
		if(!(status & 0x08))    // 检查RxIRq标志（收到数据）
		{
			return STATUS_ERROR;
		}

		// 读取FIFO中的数据
		uint8_t fifo_level = mfrc522_read_reg(dev, MFRC522_REG_FIFO_LEVEL);
		if(fifo_level < 5)    // UID应该是4字节 + BCC
		{
			return STATUS_NO_ROOM;
		}

		// 读取UID数据
		for(uint8_t i = 0; i < fifo_level; i++)
		{
			uid->uid[i] = mfrc522_read_reg(dev, MFRC522_REG_FIFO_DATA);
		}
		uid->size = fifo_level - 1; // 最后一个是BCC字节

		return STATUS_OK;
	}

	void mfrc522_soft_reset(mfrc522_device * dev)
	{
		RT_ASSERT(dev != RT_NULL);

		// 发送软复位命令
		mfrc522_write_reg(dev, MFRC522_REG_COMMAND, MFRC522_CMD_SOFT_RESET);

		// 等待复位完成
		rt_thread_mdelay(50);

		// 等待电源稳定
		while(mfrc522_read_reg(dev, MFRC522_REG_COMMAND) & (1 << 4))
		{
			rt_thread_mdelay(10);
		}
	}

#ifdef __cplusplus
}
#endif
// <<< end of configuration section >>>
/* ----------------------------- end of file.c -------------------------------- */
